package v1

import (
	"net/http"
	"sort"
	"strings"
	"sync"
)

// Router 路由接口，定义了所有路由都应实现的方法
type Router interface {
	http.Handler
	Handle(path string, handler http.Handler) bool
	HandleFunc(path string, handler http.HandlerFunc) bool
	Delete(path string)
	Mount(prefix string, subRouter Router) bool
	Unmount(prefix string) bool
}

type BasicRouter struct {
	// 精确匹配
	handleMap sync.Map
	prefix    string
	mu        sync.RWMutex

	// 循环匹配
	es []*handlerEntry // slice of entries sorted from longest to shortest.
}

// NewBasicRouter 创建新的基础路由实例
func NewBasicRouter() *BasicRouter {
	return &BasicRouter{
		prefix: "",
	}
}

func (r *BasicRouter) rebuildEs() {
	r.mu.Lock()
	defer r.mu.Unlock()
	r.es = r.es[:0]
	r.handleMap.Range(func(key, value any) bool {
		k := key.(string)
		if k[len(k)-1] == '/' {
			r.es = append(r.es, value.(*handlerEntry))
		}
		return true
	})
	sort.Slice(r.es, func(i, j int) bool {
		lenI := len(r.es[i].pattern)
		lenJ := len(r.es[j].pattern)
		if lenI != lenJ {
			return lenI > lenJ // 长路径优先
		}
		// 长度相同时按字典序（避免随机顺序）
		return r.es[i].pattern < r.es[j].pattern
	})

}

// 重复注册返回false
func (r *BasicRouter) Handle(path string, handler http.Handler) bool {
	_, loaded := r.handleMap.LoadOrStore(path, &handlerEntry{h: handler, pattern: path})
	if path[len(path)-1] == '/' {
		r.rebuildEs()
	}
	return !loaded
}

// 重复注册返回false
func (r *BasicRouter) HandleFunc(path string, handler http.HandlerFunc) bool {
	_, loaded := r.handleMap.LoadOrStore(path, &handlerEntry{h: handler, pattern: path})
	if path[len(path)-1] == '/' {
		r.rebuildEs()
	}
	return !loaded
}

func (r *BasicRouter) Delete(path string) {
	if _, ok := r.handleMap.LoadAndDelete(path); ok {
		if path[len(path)-1] == '/' {
			r.rebuildEs()
		}
	}
}

// 重复注册返回false
func (r *BasicRouter) Mount(prefix string, subRouter Router) bool {
	_, loaded := r.handleMap.LoadOrStore(prefix, &handlerEntry{prefix: strings.TrimSuffix(prefix, "/"), pattern: prefix, h: subRouter})
	if prefix[len(prefix)-1] == '/' {
		r.rebuildEs()
	}
	return !loaded
}

func (r *BasicRouter) Unmount(prefix string) bool {
	if _, ok := r.handleMap.LoadAndDelete(prefix); ok {
		if prefix[len(prefix)-1] == '/' {
			r.rebuildEs()
		}
		return true
	}
	return false
}

func TryTrimPrefix(s, prefix string) (newstr string, ok bool) {
	if len(prefix) == 0 {
		return s, false
	}

	if !strings.HasPrefix(s, prefix) {
		return s, false
	}
	return s[len(prefix):], true
}

func (r *BasicRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	path := req.URL.Path
	rec := r.match(path)
	if rec == nil {
		http.NotFound(w, req)
		return
	}
	if len(rec.prefix) > 0 {
		req.URL.Path, _ = TryTrimPrefix(path, rec.prefix)
	}
	h := rec.h.(http.Handler)
	h.ServeHTTP(w, req)
}

func (r *BasicRouter) match(path string) *handlerEntry {
	rec, _ := r.handleMap.Load(path)
	if rec != nil {
		return rec.(*handlerEntry)
	}

	r.mu.RLock()
	defer r.mu.RUnlock()
	for _, e := range r.es {
		if strings.HasPrefix(path, e.pattern) {
			return e
		}
	}

	return nil
}

type handlerEntry struct {
	h       http.Handler
	prefix  string
	pattern string
}

func appendSorted(es []*handlerEntry, e *handlerEntry) []*handlerEntry {
	n := len(es)
	i := sort.Search(n, func(i int) bool {
		return len(es[i].pattern) < len(e.pattern)
	})
	if i == n {
		return append(es, e)
	}
	// we now know that i points at where we want to insert
	es = append(es, &handlerEntry{}) // try to grow the slice in place, any entry works.
	copy(es[i+1:], es[i:])           // Move shorter entries down
	es[i] = e
	return es
}

func deleteSorted(es []*handlerEntry, pattern string) []*handlerEntry {
	i := -1
	for j, v := range es {
		if v.pattern == pattern {
			i = j
			break
		}
	}

	if i >= 0 {
		return append(es[:i], es[i+1:]...)
	} else {
		return es
	}

}

func TryTrimSuffix(s, suffix string) (newstr string, ok bool) {
	if len(suffix) == 0 {
		return s, false
	}
	if !strings.HasSuffix(s, suffix) {
		return s, false
	}
	return s[:len(s)-len(suffix)], true
}
